{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LangChain: Memory\n",
    "\n",
    "## Outline\n",
    "* ConversationBufferMemory\n",
    "* ConversationBufferWindowMemory\n",
    "* ConversationTokenBufferMemory\n",
    "* ConversationSummaryMemory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ConversationBufferMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "_ = load_dotenv(find_dotenv()) # read local .env file\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.chains import ConversationChain\n",
    "from langchain.memory import ConversationBufferMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0.0)\n",
    "memory = ConversationBufferMemory()\n",
    "conversation = ConversationChain(\n",
    "    llm=llm, \n",
    "    memory = memory,\n",
    "    verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "\n",
      "Human: Hi, my name is Andrew\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\""
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"Hi, my name is Andrew\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: Hi, my name is Andrew\n",
      "AI: Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\n",
      "Human: What is 1+1?\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The answer to 1+1 is 2.'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"What is 1+1?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "Human: Hi, my name is Andrew\n",
      "AI: Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\n",
      "Human: What is 1+1?\n",
      "AI: The answer to 1+1 is 2.\n",
      "Human: What is my name?\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Your name is Andrew, as you mentioned earlier.'"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"What is my name?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Human: Hi, my name is Andrew\n",
      "AI: Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\n",
      "Human: What is 1+1?\n",
      "AI: The answer to 1+1 is 2.\n",
      "Human: What is my name?\n",
      "AI: Your name is Andrew, as you mentioned earlier.\n"
     ]
    }
   ],
   "source": [
    "print(memory.buffer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': \"Human: Hi, my name is Andrew\\nAI: Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\\nHuman: What is 1+1?\\nAI: The answer to 1+1 is 2.\\nHuman: What is my name?\\nAI: Your name is Andrew, as you mentioned earlier.\"}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory = ConversationBufferMemory()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context({\"input\": \"Hi\"}, \n",
    "                    {\"output\": \"What's up\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Human: Hi\n",
      "AI: What's up\n"
     ]
    }
   ],
   "source": [
    "print(memory.buffer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': \"Human: Hi\\nAI: What's up\"}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context({\"input\": \"Not much, just hanging\"}, \n",
    "                    {\"output\": \"Cool\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': \"Human: Hi\\nAI: What's up\\nHuman: Not much, just hanging\\nAI: Cool\"}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ConversationBufferWindowMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.memory import ConversationBufferWindowMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory = ConversationBufferWindowMemory(k=1)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "memory.save_context({\"input\": \"Hi\"},\n",
    "                    {\"output\": \"What's up\"})\n",
    "memory.save_context({\"input\": \"Not much, just hanging\"},\n",
    "                    {\"output\": \"Cool\"})\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': 'Human: Not much, just hanging\\nAI: Cool'}"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0.0)\n",
    "memory = ConversationBufferWindowMemory(k=1)\n",
    "conversation = ConversationChain(\n",
    "    llm=llm, \n",
    "    memory = memory,\n",
    "    verbose=False\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Hello Andrew, it's nice to meet you. My name is AI. How can I assist you today?\""
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"Hi, my name is Andrew\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'The answer to 1+1 is 2.'"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"What is 1+1?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"I'm sorry, I don't have access to that information. Could you please tell me your name?\""
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"What is my name?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ConversationSummaryMemory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.memory import ConversationSummaryBufferMemory\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a long string\n",
    "schedule = \"There is a meeting at 8am with your product team. \\\n",
    "You will need your powerpoint presentation prepared. \\\n",
    "9am-12pm have time to work on your LangChain \\\n",
    "project which will go quickly because Langchain is such a powerful tool. \\\n",
    "At Noon, lunch at the italian resturant with a customer who is driving \\\n",
    "from over an hour away to meet you to understand the latest in AI. \\\n",
    "Be sure to bring your laptop to show the latest LLM demo.\"\n",
    "\n",
    "memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=100)\n",
    "memory.save_context({\"input\": \"Hello\"}, {\"output\": \"What's up\"})\n",
    "memory.save_context({\"input\": \"Not much, just hanging\"},\n",
    "                    {\"output\": \"Cool\"})\n",
    "memory.save_context({\"input\": \"What is on the schedule today?\"}, \n",
    "                    {\"output\": f\"{schedule}\"})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': 'System: The human and AI engage in small talk before the human asks about their schedule for the day. The AI informs the human of a meeting with their product team at 8am, time to work on their LangChain project from 9am-12pm, and a lunch meeting with a customer interested in the latest in AI. The AI also reminds the human to bring their laptop to show the latest LLM demo.'}"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "conversation = ConversationChain(\n",
    "    llm=llm, \n",
    "    memory = memory,\n",
    "    verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new ConversationChain chain...\u001b[0m\n",
      "Prompt after formatting:\n",
      "\u001b[32;1m\u001b[1;3mThe following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.\n",
      "\n",
      "Current conversation:\n",
      "System: The human and AI engage in small talk before the human asks about their schedule for the day. The AI informs the human of a meeting with their product team at 8am, time to work on their LangChain project from 9am-12pm, and a lunch meeting with a customer interested in the latest in AI. The AI also reminds the human to bring their laptop to show the latest LLM demo.\n",
      "Human: What would be a good demo to show?\n",
      "AI:\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"Based on the customer's interest in AI, I would recommend showing them the latest features of our Language Learning Model (LLM) and how it can be used to improve language learning outcomes. We can also showcase the accuracy and efficiency of the model by running it on some sample data. Additionally, we can demonstrate how the model can be customized to meet specific language learning needs.\""
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conversation.predict(input=\"What would be a good demo to show?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'history': \"System: The human and AI engage in small talk before the human asks about their schedule for the day. The AI informs the human of a meeting with their product team at 8am, time to work on their LangChain project from 9am-12pm, and a lunch meeting with a customer interested in the latest in AI. The AI also reminds the human to bring their laptop to show the latest LLM demo.\\nHuman: What would be a good demo to show?\\nAI: Based on the customer's interest in AI, I would recommend showing them the latest features of our Language Learning Model (LLM) and how it can be used to improve language learning outcomes. We can also showcase the accuracy and efficiency of the model by running it on some sample data. Additionally, we can demonstrate how the model can be customized to meet specific language learning needs.\"}"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "memory.load_memory_variables({})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
